#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>

typedef long long ll;
const int N = 100005;
int n, m, cnt, tot, num, rec, dfn[N], low[N], sum[N << 1];
int e_cnt, heads[N], siz[N << 1];
ll ans;
std::stack<int> stk;
std::vector<int> cc[N << 1];

struct Edge {
  int v, nxt;
} e[N << 1];

inline void add(int u, int v) {
  e[++e_cnt].v = v, e[e_cnt].nxt = heads[u], heads[u] = e_cnt;
}

void tarjan(int x) {
  dfn[x] = low[x] = ++cnt, ++num;
  stk.push(x);
  for (int i = heads[x], v; i; i = e[i].nxt) {
    if (!dfn[v = e[i].v]) {
      tarjan(v);
      low[x] = std::min(low[x], low[v]);
      if (low[v] == dfn[x]) {
        int tmp(0);
        sum[++rec] = 0;
        do {
          tmp = stk.top();
          stk.pop();
          cc[tmp].push_back(rec);
          cc[rec].push_back(tmp);
          ++sum[rec];
        } while (tmp != v);
        cc[rec].push_back(x);
        cc[x].push_back(rec);
        ++sum[rec];
      }
    } else
      low[x] = std::min(low[x], dfn[v]);
  }
}

void dfs(int x, int fa) {
  siz[x] = x <= n;
  for (auto &v : cc[x]) {
    if (v != fa) {
      dfs(v, x);
      ans += 1ll * siz[x] * siz[v] * sum[x] << 1;
      siz[x] += siz[v];
    }
  }
  ans += 1ll * sum[x] * siz[x] * (num - siz[x]) << 1;
}

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("testdata.in", "r", stdin);
  freopen("testdata.out", "w", stdout);
#else
  freopen("RoundSqrTree.in", "r", stdin);
  freopen("RoundSqrTree.out", "w", stdout);
#endif
#endif

  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; ++i) sum[i] = - 1;
  rec = n;
  for (int i = 1, u, v; i <= m; ++i) {
    scanf("%d%d", &u, &v);
    add(u, v), add(v, u);
  }
  for (int i = 1; i <= n; ++i) {
    if (!dfn[i]) {
      num = 0;
      tarjan(i);
      stk.pop();
      dfs(i, 0);
    }
  }
  printf("%lld", ans);
  return 0;
}